﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cludg.Domain.Content;
using cludg.Repository.Content;
using cludg.Repository.Transactions;
using cludg.Utils.Common;

namespace cludg.Services.Content
{
	using Domain.Content.Stories;
	using Domain.Users;

	/// <summary>
	/// Story service
	/// </summary>
	public class StoryService : IStoryService
	{
		protected readonly IContentRepository<Story> Repository;
		protected readonly ITransactionFactory TransactionFactory;

		public StoryService(IContentRepository<Story> repository, ITransactionFactory transactionFactory)
		{
			Repository = repository;
			TransactionFactory = transactionFactory;
		}

		#region Implementation of IStoryService

		/// <summary>
		/// Get all stories
		/// </summary>
		public IQueryable<Story> All
		{
			get { return Repository.Get(); }
		}

		/// <summary>
		/// Get stroy by Id
		/// </summary>
		/// <param name="storyId">Story Id</param>
		/// <returns>Story with specified Id</returns>
		public Story ById(string storyId)
		{
			return Repository.ById(storyId);
		}

		protected string PrepareUniqueName(string name)
		{
			var builder = new StringBuilder(name.Length);
			foreach (var c in name.Where(x => Char.IsLetterOrDigit(x) || Char.IsWhiteSpace(x)))
			{
				if (Char.IsWhiteSpace(c))
				{
					builder.Append('-');
				}
				else
				{
					builder.Append(c);
				}
			}
			return Transliteration.Front(builder.ToString());
		}

		protected string GenerateUniqueName(Story story)
		{
			var baseName = PrepareUniqueName(story.Title);
			if (String.IsNullOrWhiteSpace(baseName))
				baseName = PrepareUniqueName(DateTime.Now.ToString());
			var name = baseName;
			int index = 1;
			while (Repository.Get().Any(x => x.UniqueName == name))
			{
				index++;
				name = String.Format("{0}{1}", baseName, index);
			}
			return name;
		}

		/// <summary>
		/// Create new story
		/// </summary>
		/// <param name="subject">Story subject</param>
		/// <param name="author">Story author</param>
		/// <param name="offerAuthor">Offer author</param>
		/// <param name="title">Story title</param>
		/// <param name="body">Story body</param>
		/// <param name="anonymouseAutorName">Anonumouse Author name</param>
		/// <param name="tags">Tags string</param>
		/// <returns>Created story</returns>
		public Story NewStory(StorySubject subject, User author, User offerAuthor, string title, string body, string anonymouseAutorName,
			string tags)
		{
			var addingStory = new Story
				{
					Author = author,
					OfferAuthor = offerAuthor,
					Body = body,
					Title = title,
					Subject = subject,
					AnonymouseAuthorName = anonymouseAutorName,
					CreationTime = DateTime.Now,
				};
			// TODO: разделитель в настройки
			addingStory.SetTagsAsString(tags, ',');

			using (var tx = TransactionFactory.BeginTransaction())
			{
				addingStory.UniqueName = GenerateUniqueName(addingStory);
				Repository.Add(addingStory);
				tx.Commit();
			}
			return addingStory;
		}

		public void DeleteStory(Story story)
		{
			using (var tx = TransactionFactory.BeginTransaction())
			{
				Repository.Delete(story);
				tx.Commit();
			}
		}

		public void EditStory(Story story, string newTitle, string newBody, string newTags)
		{
			using (var tx = TransactionFactory.BeginTransaction())
			{
				story.Title = newTitle;
				story.Body = newBody;
				story.SetTagsAsString(newTags, ',');
				Repository.Save(story);
				tx.Commit();
			}
		}
		#endregion
	}
}
